bitkeeper revision 1.1159.180.2 (419dc71eHwyXT3BVHFdxBKRp1BPxFw)
authorkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Fri, 19 Nov 2004 10:12:46 +0000 (10:12 +0000)
committerkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Fri, 19 Nov 2004 10:12:46 +0000 (10:12 +0000)
Add return codes to exception handlers to indicate if a fault was fixed
up and so instruction replay ought to work.

xen/arch/x86/memory.c
xen/arch/x86/shadow.c
xen/arch/x86/traps.c
xen/include/asm-x86/debugger.h
xen/include/asm-x86/processor.h

index fafbb404918bc3d338dc55c03c0f119ab78d51e4..d9d10ca29a9e0e1cbd6f435967f662efa484337e 100644 (file)
@@ -1809,8 +1809,7 @@ int ptwr_do_page_fault(unsigned long addr)
         domain_crash();
     }
     
-    /* Maybe fall through to shadow mode to propagate writable L1. */
-    return !current->mm.shadow_mode;
+    return EXCRET_fault_fixed;
 }
 
 static __init int ptwr_init(void)
index 4c0512ade8fcfb1d5fedb9bcc6851977a87a4378..77b09551d940027c50997e4eb675740782efb6cf 100644 (file)
@@ -636,7 +636,7 @@ int shadow_fault(unsigned long va, long error_code)
     shadow_unlock(m);
 
     check_pagetable(m, current->mm.pagetable, "post-sf");
-    return 1;
+    return EXCRET_fault_fixed;
 }
 
 
index 7b7c07142c6673d63a85ac80971c598980e5532c..29fb3a66e05c7b87cdbce7bfa02d0a2675e45e9d 100644 (file)
@@ -228,7 +228,7 @@ asmlinkage void fatal_trap(int trapnr, struct xen_regs *regs, long error_code)
         __asm__ __volatile__ ( "hlt" );
 }
 
-static inline void do_trap(int trapnr, char *str,
+static inline int do_trap(int trapnr, char *str,
                            struct xen_regs *regs, 
                            long error_code, int use_error_code)
 {
@@ -249,7 +249,7 @@ static inline void do_trap(int trapnr, char *str,
     tb->eip        = ti->address;
     if ( TI_GET_IF(ti) )
         d->shared_info->vcpu_data[0].evtchn_upcall_mask = 1;
-    return
+    return 0;
 
  xen_fault:
 
@@ -257,7 +257,7 @@ static inline void do_trap(int trapnr, char *str,
     {
         DPRINTK("Trap %d: %08lx -> %08lx\n", trapnr, regs->eip, fixup);
         regs->eip = fixup;
-        return;
+        return 0;
     }
 
     DEBUGGER_trap_fatal(trapnr, regs, error_code);
@@ -266,18 +266,19 @@ static inline void do_trap(int trapnr, char *str,
     panic("CPU%d FATAL TRAP: vector = %d (%s)\n"
           "[error_code=%08x]\n",
           smp_processor_id(), trapnr, str, error_code);
+    return 0;
 }
 
 #define DO_ERROR_NOCODE(trapnr, str, name) \
-asmlinkage void do_##name(struct xen_regs * regs, long error_code) \
+asmlinkage int do_##name(struct xen_regs * regs, long error_code) \
 { \
-    do_trap(trapnr, str, regs, error_code, 0); \
+    return do_trap(trapnr, str, regs, error_code, 0); \
 }
 
 #define DO_ERROR(trapnr, str, name) \
-asmlinkage void do_##name(struct xen_regs * regs, long error_code) \
+asmlinkage int do_##name(struct xen_regs * regs, long error_code) \
 { \
-    do_trap(trapnr, str, regs, error_code, 1); \
+    return do_trap(trapnr, str, regs, error_code, 1); \
 }
 
 DO_ERROR_NOCODE( 0, "divide error", divide_error)
@@ -292,7 +293,7 @@ DO_ERROR_NOCODE(16, "fpu error", coprocessor_error)
 DO_ERROR(17, "alignment check", alignment_check)
 DO_ERROR_NOCODE(19, "simd error", simd_coprocessor_error)
 
-asmlinkage void do_int3(struct xen_regs *regs, long error_code)
+asmlinkage int do_int3(struct xen_regs *regs, long error_code)
 {
     struct domain *d = current;
     struct trap_bounce *tb = &d->thread.trap_bounce;
@@ -316,6 +317,8 @@ asmlinkage void do_int3(struct xen_regs *regs, long error_code)
     tb->eip        = ti->address;
     if ( TI_GET_IF(ti) )
         d->shared_info->vcpu_data[0].evtchn_upcall_mask = 1;
+
+    return 0;
 }
 
 asmlinkage void do_double_fault(void)
@@ -355,7 +358,7 @@ asmlinkage void do_machine_check(struct xen_regs *regs, long error_code)
     fatal_trap(TRAP_machine_check, regs, error_code);
 }
 
-asmlinkage void do_page_fault(struct xen_regs *regs, long error_code)
+asmlinkage int do_page_fault(struct xen_regs *regs, long error_code)
 {
     trap_info_t *ti;
     unsigned long off, addr, fixup;
@@ -377,18 +380,22 @@ asmlinkage void do_page_fault(struct xen_regs *regs, long error_code)
                       ptwr_info[cpu].ptinfo[PTWR_PT_ACTIVE].l2_idx) )
         {
             ptwr_flush(PTWR_PT_ACTIVE);
-            return;
+            return EXCRET_fault_fixed;
         }
 
         if ( (addr < PAGE_OFFSET) &&
              ((error_code & 3) == 3) && /* write-protection fault */
              ptwr_do_page_fault(addr) )
-            return;
+        {
+            if ( unlikely(d->mm.shadow_mode) )
+                (void)shadow_fault(addr, error_code);
+            return EXCRET_fault_fixed;
+        }
     }
 
     if ( unlikely(d->mm.shadow_mode) && 
          (addr < PAGE_OFFSET) && shadow_fault(addr, error_code) )
-        return; /* Returns TRUE if fault was handled. */
+        return EXCRET_fault_fixed;
 
     if ( unlikely(addr >= LDT_VIRT_START) && 
          (addr < (LDT_VIRT_START + (d->mm.ldt_ents*LDT_ENTRY_SIZE))) )
@@ -400,7 +407,7 @@ asmlinkage void do_page_fault(struct xen_regs *regs, long error_code)
         off  = addr - LDT_VIRT_START;
         addr = d->mm.ldt_base + off;
         if ( likely(map_ldt_shadow_page(off >> PAGE_SHIFT)) )
-            return; /* successfully copied the mapping */
+            return EXCRET_fault_fixed; /* successfully copied the mapping */
     }
 
     if ( unlikely(!(regs->cs & 3)) )
@@ -414,7 +421,7 @@ asmlinkage void do_page_fault(struct xen_regs *regs, long error_code)
     tb->eip        = ti->address;
     if ( TI_GET_IF(ti) )
         d->shared_info->vcpu_data[0].evtchn_upcall_mask = 1;
-    return; 
+    return 0
 
  xen_fault:
 
@@ -424,7 +431,7 @@ asmlinkage void do_page_fault(struct xen_regs *regs, long error_code)
         if ( !d->mm.shadow_mode )
             DPRINTK("Page fault: %08lx -> %08lx\n", regs->eip, fixup);
         regs->eip = fixup;
-        return;
+        return 0;
     }
 
     DEBUGGER_trap_fatal(TRAP_page_fault, regs, error_code);
@@ -451,9 +458,10 @@ asmlinkage void do_page_fault(struct xen_regs *regs, long error_code)
           "[error_code=%08x]\n"
           "Faulting linear address might be %08lx\n",
           smp_processor_id(), error_code, addr);
+    return 0;
 }
 
-asmlinkage void do_general_protection(struct xen_regs *regs, long error_code)
+asmlinkage int do_general_protection(struct xen_regs *regs, long error_code)
 {
     struct domain *d = current;
     struct trap_bounce *tb = &d->thread.trap_bounce;
@@ -502,7 +510,7 @@ asmlinkage void do_general_protection(struct xen_regs *regs, long error_code)
     if ( VM_ASSIST(d, VMASST_TYPE_4gb_segments) && 
          (error_code == 0) && 
          gpf_emulate_4gb(regs) )
-        return;
+        return 0;
 #endif
 
     /* Pass on GPF as is. */
@@ -514,7 +522,7 @@ asmlinkage void do_general_protection(struct xen_regs *regs, long error_code)
     tb->eip        = ti->address;
     if ( TI_GET_IF(ti) )
         d->shared_info->vcpu_data[0].evtchn_upcall_mask = 1;
-    return;
+    return 0;
 
  gp_in_kernel:
 
@@ -522,7 +530,7 @@ asmlinkage void do_general_protection(struct xen_regs *regs, long error_code)
     {
         DPRINTK("GPF (%04lx): %08lx -> %08lx\n", error_code, regs->eip, fixup);
         regs->eip = fixup;
-        return;
+        return 0;
     }
 
     DEBUGGER_trap_fatal(TRAP_gp_fault, regs, error_code);
@@ -530,6 +538,7 @@ asmlinkage void do_general_protection(struct xen_regs *regs, long error_code)
     show_registers(regs);
     panic("CPU%d GENERAL PROTECTION FAULT\n"
           "[error_code=%08x]\n", smp_processor_id(), error_code);
+    return 0;
 }
 
 asmlinkage void mem_parity_error(struct xen_regs *regs)
@@ -549,8 +558,6 @@ asmlinkage void io_check_error(struct xen_regs *regs)
 
 static void unknown_nmi_error(unsigned char reason, struct xen_regs * regs)
 {
-    DEBUGGER_trap_entry(TRAP_nmi, regs, 0);
-
     printk("Uhhuh. NMI received for unknown reason %02x.\n", reason);
     printk("Dazed and confused, but trying to continue\n");
     printk("Do you have a strange power saving mode enabled?\n");
@@ -581,7 +588,7 @@ static void nmi_softirq(void)
         send_guest_virq(dom0, VIRQ_IO_ERR);
 }
 
-asmlinkage void math_state_restore(struct xen_regs *regs, long error_code)
+asmlinkage int math_state_restore(struct xen_regs *regs, long error_code)
 {
     /* Prevent recursion. */
     clts();
@@ -602,9 +609,11 @@ asmlinkage void math_state_restore(struct xen_regs *regs, long error_code)
         tb->cs         = current->thread.traps[7].cs;
         tb->eip        = current->thread.traps[7].address;
     }
+
+    return EXCRET_fault_fixed;
 }
 
-asmlinkage void do_debug(struct xen_regs *regs, long error_code)
+asmlinkage int do_debug(struct xen_regs *regs, long error_code)
 {
     unsigned int condition;
     struct domain *d = current;
@@ -619,7 +628,7 @@ asmlinkage void do_debug(struct xen_regs *regs, long error_code)
          (d->thread.debugreg[7] == 0) )
     {
         __asm__("movl %0,%%db7" : : "r" (0));
-        return;
+        goto out;
     }
 
     if ( (regs->cs & 3) == 0 )
@@ -632,7 +641,7 @@ asmlinkage void do_debug(struct xen_regs *regs, long error_code)
          * on it. No need to bump EIP; the only faulting trap is an instruction
          * breakpoint, which can't happen to us.
          */
-        return;
+        goto out;
     }
 
     /* Save debug status register where guest OS can peek at it */
@@ -641,13 +650,16 @@ asmlinkage void do_debug(struct xen_regs *regs, long error_code)
     tb->flags = TBF_TRAP_NOCODE;
     tb->cs    = d->thread.traps[1].cs;
     tb->eip   = d->thread.traps[1].address;
-}
-
 
-asmlinkage void do_spurious_interrupt_bug(struct xen_regs * regs,
-                                          long error_code)
-{ /* nothing */ }
+ out:
+    return EXCRET_not_a_fault;
+}
 
+asmlinkage int do_spurious_interrupt_bug(
+    struct xen_regs * regs, long error_code)
+{
+    return EXCRET_not_a_fault;
+}
 
 #define _set_gate(gate_addr,type,dpl,addr) \
 do { \
index b19e099a9f7c0ad177f72ab1b863a0d6d27c04a8..4b32491d1564de4388a19685d923904957a6c0a0 100644 (file)
 #ifndef __X86_DEBUGGER_H__
 #define __X86_DEBUGGER_H__
 
-/* Avoid magic vector numbers by using these semi-sensical names. */
-#define TRAP_divide_error     0
-#define TRAP_debug            1
-#define TRAP_nmi              2
-#define TRAP_int3             3
-#define TRAP_overflow         4
-#define TRAP_bounds           5
-#define TRAP_invalid_op       6
-#define TRAP_no_device        7
-#define TRAP_double_fault     8
-#define TRAP_copro_seg        9
-#define TRAP_invalid_tss     10
-#define TRAP_no_segment      11
-#define TRAP_stack_error     12
-#define TRAP_gp_fault        13
-#define TRAP_page_fault      14
-#define TRAP_spurious_int    15
-#define TRAP_copro_error     16
-#define TRAP_alignment_check 17
-#define TRAP_machine_check   18
-#define TRAP_simd_error      19
+#include <asm/processor.h>
 
 /* The main trap handlers use these helper macros which include early bail. */
 #define DEBUGGER_trap_entry(_v, _r, _e) \
-    if ( debugger_trap_entry(_v, _r, _e) ) return;
+    if ( debugger_trap_entry(_v, _r, _e) ) return EXCRET_fault_fixed;
 #define DEBUGGER_trap_fatal(_v, _r, _e) \
-    if ( debugger_trap_fatal(_v, _r, _e) ) return;
+    if ( debugger_trap_fatal(_v, _r, _e) ) return EXCRET_fault_fixed;
 
 #ifdef XEN_DEBUGGER
 
index 81d35ad3248e1a01ac836586b942af2a77abd062..81ce7fab402fbfbd604f60f5be714949ad1284d2 100644 (file)
 #define X86_CR4_OSFXSR         0x0200  /* enable fast FPU save and restore */
 #define X86_CR4_OSXMMEXCPT     0x0400  /* enable unmasked SSE exceptions */
 
+/*
+ * Trap/fault mnemonics.
+ */
+#define TRAP_divide_error     0
+#define TRAP_debug            1
+#define TRAP_nmi              2
+#define TRAP_int3             3
+#define TRAP_overflow         4
+#define TRAP_bounds           5
+#define TRAP_invalid_op       6
+#define TRAP_no_device        7
+#define TRAP_double_fault     8
+#define TRAP_copro_seg        9
+#define TRAP_invalid_tss     10
+#define TRAP_no_segment      11
+#define TRAP_stack_error     12
+#define TRAP_gp_fault        13
+#define TRAP_page_fault      14
+#define TRAP_spurious_int    15
+#define TRAP_copro_error     16
+#define TRAP_alignment_check 17
+#define TRAP_machine_check   18
+#define TRAP_simd_error      19
+
+/*
+ * Non-fatal fault/trap handlers return an error code to the caller. If the
+ * code is non-zero, it means that either the exception was not due to a fault
+ * (i.e., it was a trap) or that the fault has been fixed up so the instruction
+ * replay ought to succeed.
+ */
+#define EXCRET_not_a_fault 1 /* It was a trap. No instruction replay needed. */
+#define EXCRET_fault_fixed 1 /* It was fault that we fixed: try a replay. */
+
 /*
  * 'trap_bounce' flags values.
  */